//este objeto mantiene una estructura jerarquica para la representacion de los edificio, pisos, spaces, portales, etc
function modelo_jerarquia_spaces(controller){
	
	var _controller = controller; //CONTROLLER_JERARQUIA_SPACES
	var _nodos = {}; //mantiene la jerarquia de pisos/spaces/portals/niveles
					//TODO agregar soporte para basemaps 
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- GET SPACE --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	this.getSpace = function(nombreEdificio, nombrePiso, nombreSpace){
		
		
		//console.log("en modelo jerarquia spaces", nombreEdificio, nombrePiso, nombreSpace);
		if (_nodos[nombreEdificio] && _nodos[nombreEdificio][nombrePiso]){
			
			if (_nodos[nombreEdificio][nombrePiso]["spaces"][nombreSpace]){
				return _nodos[nombreEdificio][nombrePiso]["spaces"][nombreSpace];
			}
			
			//si no se pasa el nombre del space como parametro, retorno el space de referencia dentro del piso
			if (!nombreSpace){
				return _nodos[nombreEdificio][nombrePiso].referenceNode;
			}
			
		}
		else{
			alert("ERROR. en modelo jerarquia spaces. getSpace");
			return null;
		}
	};
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- GET FLOOR --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	this.getFloor = function(nombreEdificio, nombrePiso){
		if (_nodos[nombreEdificio] && _nodos[nombreEdificio][nombrePiso]){
			return _nodos[nombreEdificio][nombrePiso];
		}
		else{
			alert("ERROR. en modelo jerarquia spaces. getFloor");
			return null;
		}
	};
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- GET FLOORS FROM A LEVEL --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	this.getFloorsFromLevel = function(nombreEdificio, nombreNivel){
		if (_nodos[nombreEdificio] && _nodos[nombreEdificio].niveles[nombreNivel] && _nodos[nombreEdificio].niveles[nombreNivel].pisos){
			return _nodos[nombreEdificio].niveles[nombreNivel].pisos;
		}
		else{
			alert("ERROR. en modelo jerarquia spaces. getFloorsFromLevel");
			return null;
		}
	};
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- GET RANDOM LEVEL --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//para la inicializacion, necesito un nivel para mostrar (si es que no viene el nivel por defecto en algun archivo)
	//<nombreEdificio> : nombre del edificio del que se retornara un nivel
	//return: valor del nivel (numero)
	this.getRandomLevel = function(nombreEdificio){
		  var level = null;
		  for (var i = 0; i<10; i++){
			  if (_nodos[nombreEdificio]["niveles"][i] != undefined){
				  level = i;
				  break;
			  }
		  };
		  return level;
	};
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- EXISTE PISO --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//retorna true si existe el piso en dicho edificio. false en caso contrario
	this.existePiso = function(nombreEdificio, nombrePiso){
		var edificio = _nodos[nombreEdificio];
		if (!edificio) return false;
		return (edificio[nombrePiso])? true : false;
	};
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- EXISTE NIVEL --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//retorna true si existe el piso en dicho edificio. false en caso contrario
	this.existeNivel = function(nombreEdificio, nombreNivel){
		var edificio = _nodos[nombreEdificio];
		if (!edificio) return false;
		return (edificio.niveles[nombreNivel])? true : false;
	};
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- GET PORTAL INTRA SPACES ID --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	this.getPortalIntraSpacesID = function(nombreEdificio, nombrePiso, sourceSpaceName, targetSpaceName){
		var sourceSpace = _nodos[nombreEdificio][nombrePiso]["spaces"][sourceSpaceName];
		var targetSpace = _nodos[nombreEdificio][nombrePiso]["spaces"][targetSpaceName];//se supone que va a estar en el mismo piso y edificio
		
		var portalID = null;
		for (var k = 0, l = sourceSpace.outgoingPortals.length; k < l; k++){
			if (sourceSpace.outgoingPortals[k].getNextSpace(sourceSpace) == targetSpace){
				portalID = sourceSpace.outgoingPortals[k].id;
				break;
			} 
		}
		
		return portalID;
	};
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- INSERTAR PISO DESDE ARCHIVO --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//recibe los datos, provenientes de un JSON de un piso, y crea el edificio, piso, spaces, etc (si no existen previamente)
	this.insertarPisoDesdeArchivo = function(nombreEdificio, data){
			var edificio = this.crearEdificio(nombreEdificio);
			this.crearNivel(edificio, data.floor.level);
			this.crearPiso(edificio, data);
	};
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- CREAR EDIFICIO --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//<nombre> : nombre del edificio a crear
	//
	//<return> : puntero al edificio
	this.crearEdificio = function (nombre){
		var edificio = _nodos[nombre];
		if (edificio) return edificio; //ya existe un edificio con el mismo ID
		
		 edificio = _nodos[nombre] = {};//TODO ver si funciona
		 edificio.nombre = nombre;
		 edificio.niveles = [];
		 return edificio; //exito al crear el edificio
	};
	
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- CREAR NIVEL --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	//<edificio> : puntero al edificio en el que se desea crear un nuevo nivel
	//<nivel> : valor del nivel que se quiere crear
	//
	//<return> : puntero al nivel
	this.crearNivel = function (edificio, nivel){
		
		if (edificio && edificio.niveles && edificio.niveles[nivel]) return edificio.niveles[nivel]; //ya existe el nivel para este edificio
		
		 var nivelObj = edificio.niveles[nivel] = {}; //TODO ver si funcina
		 nivelObj.pisos = [];
		 nivelObj.indice = nivel;
		 nivelObj.tipo = "nivel";//TODO
		 nivelObj.clase = "nivel";
		 nivelObj.buildingName = edificio.nombre;
		 
		 _controller.pushObject(nivelObj);//para crear la representacion visual
		 
		 return nivelObj;
	};
	

	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- CREAR PISO --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	this.crearPiso = function(edificio, data){	
		
		if(edificio[data.floor.name]) { //el piso ya existe
			//alert("el piso ya existe");
			return null;
		}; 
		
		//creamos el piso
		data.floor.buildingName = edificio.nombre; //hardcodeado
		var pisoCreado = new Piso(data); 
		
		//creamos y/o linkeamos portales interfloors
		//los potales intrafloor son creado y linkeados en la creacion el piso
		linkearPortalesInterFloor(data, pisoCreado);
		
		//asociamos el piso creado al edificio
		edificio[pisoCreado.id] = pisoCreado; 
		
		//asociamos el piso creado al nivel dentro del edificio
		edificio.niveles[pisoCreado.level].pisos.push(pisoCreado); 
				
	};
	
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- LINKEAR PORTALES INTER FLOOR --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	function linkearPortalesInterFloor(dataPiso, piso){
		if (!piso.portals || !piso.portals.length) return;
		
		var portals = dataPiso.portals;
		for (var i = 0, l = portals.length; i < l; i++){
			var portal = portals[i]; 
			if (portal.class_ != "inter_floor") continue;
			
			var sourceID = piso.buildingName+"/"+piso.name+"/"+portal.sourceID; //armo el path absoluto
			linkearPortalInterFloor(sourceID, portal, piso);
		};
	}
	
	
	//---------------------------------------------------------------------------------------------------------------------
	//----------------------------------- LINKEAR PORTAL INTER FLOOR --------------------------------------------
	//---------------------------------------------------------------------------------------------------------------------
	function linkearPortalInterFloor(sourcePathAbsoluto, portalArchivo, pisoCreado){
		
		if (!portalArchivo.targetID) return; //no tengo informacion del otro extremo del portal
											//el portal no esta linkeado, problema desde el editor! //TODO
		
		//splitteo el path absoluto 'edificio/piso/space'
		var componentes = portalArchivo.targetID.split("\/");
		
		//hago asignaciones a otras variables para que sea mas facil de modificar
		//dsp usar 'componentes' indexado nomas (mejorar eficiencia)
		if (componentes.length < 3){alert('error!'); return;}
		var nombreEdificioTarget = componentes[0];
		var nombrePisoTarget = componentes[1];
		var nombreSpaceTarget = componentes[2];
		
		
		var spaceSource = pisoCreado["spaces"][portalArchivo.sourceID];
		
		
		if (_nodos[nombreEdificioTarget][nombrePisoTarget] == undefined 
			|| _nodos[nombreEdificioTarget][nombrePisoTarget]["spaces"][nombreSpaceTarget] == undefined){
			
			//dangling portal (asumo xq es de tipo 'door', que el otro space va a estar en el mismo nivel)
			//creamos el portal: el otro extremo todavia no existe
			var portal = new Portal(portalArchivo, pisoCreado);
			
			pisoCreado["portals"].push(portal);
			_controller.pushObject(portal);//para crear la representacion visual (dangling)
			
		}else{ //el target existe. linkear el portal con el otro extremo 
			
			var targetSpace = _nodos[nombreEdificioTarget][nombrePisoTarget]["spaces"][nombreSpaceTarget];
			if (!targetSpace) alert('link portals: target es NULL');
			
			var linkie = false;
			for (var i = 0, l = targetSpace.outgoingPortals.length; i < l; i++){
				
				var portal = targetSpace.outgoingPortals[i]; 
				if (portal.targetID == sourcePathAbsoluto) {
				
					portal.targetSpace = spaceSource; //linkee
					
//					if (portalArchivo.targetID == "Alem/CA_PB/45"){
//						var uno = 1;
//						uno++;
//					}
					portal.completeContour(portalArchivo.p1, portalArchivo.p2);//completo el contorno del portal
					
					spaceSource.outgoingPortals.push(targetSpace.outgoingPortals[i]);

//					console.log('linkie portales interfloor','source--> ', sourcePathAbsoluto, ' target-->', portalArchivo.targetID );
					
					//TODO. esto lo dejo aca??????
					portal.tipo = "portal_inter_floor";
					portal.height = targetSpace.height;
					_controller.pushObject(portal);//para crear la representacion visual
					//alert("linkie");
					linkie = true;
					break;
				}
			}
			
			if (!linkie){
				console.log("no linkie!!!!!!!!!!!!", sourcePathAbsoluto, portalArchivo, pisoCreado);
			}
			
		}
	}
	
};